package com.asset.modules.common.handler;

import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.alibaba.excel.exception.ExcelDataConvertException;
import com.alibaba.fastjson.JSON;
import com.asset.modules.assets.model.Asset;
import com.asset.modules.assets.service.AssetService;
import com.asset.modules.common.utils.Calcutil;
import com.asset.modules.common.utils.CodeGenerator;
import com.asset.modules.system.model.Project;
import com.asset.modules.system.service.ProjectService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * @author chenchen
 */
@Component
public class AssetListener extends AnalysisEventListener<Asset> {

    private static final Logger LOG  = LoggerFactory.getLogger(AssetListener.class);
    /**
     * 每隔100条存储数据库
     *
     *
     */
    private ProjectService ps;

    private AssetService as;

    public AssetListener(ProjectService ps, AssetService as){
        this.ps = ps;
        this.as = as;
    }


    private static final int BATCH_COUNT = 100;
    List<Asset> list = new ArrayList<Asset>();

    //TODO Asset存储服务


    /**
     * 转换异常的情况下会调用本接口
     * @param exception
     * @param context
     * @throws Exception
     */
    @Override
    public void onException(Exception exception, AnalysisContext context) throws Exception {
        LOG.error("解析失败，但是继续解析下一行:{}", exception.getMessage());
        if(exception instanceof ExcelDataConvertException){
            ExcelDataConvertException excelDataConvertException = (ExcelDataConvertException)exception;
            LOG.error("第{}行，第{}列解析异常，数据为:{}", excelDataConvertException.getRowIndex(),
                    excelDataConvertException.getColumnIndex(), excelDataConvertException.getCellData());
        }
    }

    /**
     * 读取头数据
     * @param headMap
     * @param context
     */
    @Override
    public void invokeHeadMap(Map<Integer, String> headMap, AnalysisContext context) {
        LOG.info("解析到一条头数据:{}", JSON.toJSONString(headMap));
        //super.invokeHeadMap(headMap, context);
    }

    /**
     * 每一条数据解析都会来调用
     * @param asset
     * @param analysisContext
     */
    @Override
    public void invoke(Asset asset, AnalysisContext analysisContext) {
        LOG.info("解析到一条数据:{}", JSON.toJSONString(asset));
        list.add(asset);
        if(list.size()>BATCH_COUNT){
           saveData();
           list.clear();
        }
    }

    /**
     * 所有数据解析完成了 都回来调用
     * @param analysisContext
     */
    @Override
    public void doAfterAllAnalysed(AnalysisContext analysisContext) {
        saveData();
    }

    /**
     * 保存数据，同时设置相关字段
     */
    private void saveData(){
        LOG.info("{}条数据，开始存储数据库！", list.size());
        //批量存储
        for(Asset a : list){
            a.setId(null);
            Project p = this.ps.getProjectByName(a.getProjectName().trim());
            a.setManageCode(CodeGenerator.generateManageCode(p.getProjectCode().trim()));
            a.setStatus("0");
            a.setProjectId(p.getId().toString());
            a.setProjectCode(p.getProjectCode());
            a.setCompanyId(p.getCompanyId());
            a.setCompanyCode(p.getCompanyCode());

            //计算净值
//            try {
//               Double value =  Calcutil
//                       .calcValue(String.valueOf(a.getRegisterMoney()), a.getBuyTime(), a.getTotalYear(), new SimpleDateFormat("yyyy-MM-dd")
//                               .format(new Date()));
//               a.setValue(value);
//            } catch (ParseException e) {
//                e.printStackTrace();
//            }

            //TODO 1.盈亏 数量（实际盘点数-账目数）； 价值 单价*（实际盘点数-账目数）；
            //盈亏数量，如果
            if(a.getCheckNum()!=null){
                a.setEarnMun(a.getCheckNum()-a.getRegisterNum());
            }else{
                a.setEarnMun(-a.getRegisterNum());
            }

            double registerMoney = a.getRegisterMoney();
            long registerNum   = a.getRegisterNum();

            //盈亏金额,先算出单价，再与盘点的数量相乘
            a.setEarnMoney((registerMoney/registerNum)*a.getEarnMun());

            this.as.saveOrUpdate(a);
        }
        LOG.info("存储数据成功！");
    }



}
